using System.Configuration;

namespace Altairis.Web.Management.Configuration {

    public enum SslRedirectorAction {
        None,
        ForceSecure,
        ForceUnsecure
    }

    public enum SniFallbackAction {
        Off,
        UseUnsecure,
        UseAlternatePort
    }

    public class SslRedirectorElement : ConfigurationElement {

        [ConfigurationProperty("enabled", DefaultValue = false, IsRequired = false)]
        public bool Enabled {
            get { return (bool)this["enabled"]; }
            set { this["enabled"] = value; }
        }

        [ConfigurationProperty("excludeSystemUrls", DefaultValue = true, IsRequired = false)]
        public bool ExcludeSystemUrls {
            get { return (bool)this["excludeSystemUrls"]; }
            set { this["excludeSystemUrls"] = value; }
        }

        [ConfigurationProperty("excludeLocalRequests", IsRequired = false, DefaultValue = true)]
        public bool ExcludeLocalRequests {
            get { return (bool)this["excludeLocalRequests"]; }
            set { this["excludeLocalRequests"] = value; }
        }

        [ConfigurationProperty("securePort", DefaultValue = 443, IsRequired = false)]
        [IntegerValidator(MinValue = 1, MaxValue = 65535)]
        public int SecurePort {
            get { return (int)this["securePort"]; }
            set { this["securePort"] = value; }
        }

        [ConfigurationProperty("unsecurePort", DefaultValue = 80, IsRequired = false)]
        [IntegerValidator(MinValue = 1, MaxValue = 65535)]
        public int UnsecrePort {
            get { return (int)this["unsecurePort"]; }
            set { this["unsecurePort"] = value; }
        }

        [ConfigurationProperty("sniAlternatePort", IsRequired = false, DefaultValue = 8000)]
        [IntegerValidator(MinValue = 1, MaxValue = 65535)]
        public int SniAlternatePort {
            get { return (int)this["sniAlternatePort"]; }
            set { this["sniAlternatePort"] = value; }
        }

        [ConfigurationProperty("defaultAction", DefaultValue = SslRedirectorAction.None, IsRequired = false)]
        public SslRedirectorAction DefaultAction {
            get { return (SslRedirectorAction)this["defaultAction"]; }
            set { this["defaultAction"] = value; }
        }

        [ConfigurationProperty("sniFallbackAction", IsRequired = false, DefaultValue = SniFallbackAction.Off)]
        public SniFallbackAction SniFallbackAction {
            get { return (SniFallbackAction)this["sniFallbackAction"]; }
            set { this["sniFallbackAction"] = value; }
        }

        [ConfigurationProperty("rules", IsDefaultCollection = true, IsRequired = true)]
        [ConfigurationCollection(typeof(SslRedirectorRuleElement))]
        public SslRedirectorRuleCollection Rules {
            get { return this["rules"] as SslRedirectorRuleCollection; }
            set { this["rules"] = value; }
        }

        [ConfigurationProperty("verbs", IsRequired = false, DefaultValue = "GET")]
        [RegexStringValidator("^([A-Z]+[, ]?)+$")]
        public string Verbs {
            get { return (string)this["verbs"]; }
            set { this["verbs"] = value; }
        }
    }

    public class SslRedirectorRuleElement : ConfigurationElement {

        [ConfigurationProperty("virtualPath", IsRequired = true, IsKey = true)]
        public string VirtualPath {
            get { return (string)this["virtualPath"]; }
            set { this["virtualPath"] = value; }
        }

        [ConfigurationProperty("action", IsRequired = true)]
        public SslRedirectorAction Action {
            get { return (SslRedirectorAction)this["action"]; }
            set { this["action"] = value; }
        }
    }

    public class SslRedirectorRuleCollection : ConfigurationElementCollection {

        protected override ConfigurationElement CreateNewElement() {
            return new SslRedirectorRuleElement();
        }

        protected override object GetElementKey(ConfigurationElement element) {
            return ((SslRedirectorRuleElement)element).VirtualPath;
        }

        new public SslRedirectorRuleElement this[string virtualPath] {
            get {
                return this.BaseGet(virtualPath) as SslRedirectorRuleElement;
            }
        }
    }
}